home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’92 / Insomnia / Insomnia.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  6.0 KB  |  242 lines  |  [TEXT/KAHL]

  1. /* init to disable power mgr idling on plugged-in-ness of charger
  2.  
  3.     © 1992 by Stephan Somogyi, all rights reserved
  4.  
  5.     The source code below may not be used in a commercial product without the written consent
  6.     of the author. It may, however, be used in not-for-profit software, provided that
  7.     adequate attribution of its origin is given.
  8.  
  9.     This source code is freely distributable if unaltered.
  10.  
  11.  
  12.     06.06.92            0.1.0    MacPCP
  13.     09.06.92            0.1.1    various source cleanings up
  14.                                 renamed to Insomnia
  15.     13.06.92            0.2.0    added use of deferred task mgr per dts' suggetion
  16.                                 compiled with MPW to check for sillinesses that think won't catch
  17.     14.06.92            0.3        added separate code & icons for DetachResource and VInstall errs
  18.                                 built version with DEBUG support
  19.     15.06.92            0.3.1    added StripAddresses everywhere. dunno if it'll help. sigh.
  20.     17.06.92            0.4        added SaveTheWorld/RestoreTheWorld
  21.                         0.4.1    added lotsa comments and cleaned up a bit
  22.     18.06.92            0.4.2    removed StripAddresses again because they seem somewhat pointless
  23.                         0.4.3    added zeroing of all unused fields in the DeferredTaskBlock in
  24.                                 every vbl
  25.                         1.0a1    released at MacHack.
  26.                                 the 1st person who finds the bug and tells me gets a t-shirt.
  27.  
  28.  
  29.     my weird source code conventions: any identifier beginning with a
  30.  
  31.     k    is a constant
  32.     g    is a global var
  33.     l    is a local var
  34.  
  35. */
  36.  
  37.  
  38. /*    the #ifndef below speeds up think compiles since the .h files in question are in macheaders.
  39.     without it, however, the c part of this won't compile under mpw. the down-side of this is no
  40.     automatic access to the .h files via the title-bar in the think environment.
  41. */
  42.  
  43. #ifndef THINK_C
  44.     #include <Traps.h>
  45.     #include <GestaltEqu.h>
  46.     #include <Resources.h>
  47.     #include <OSUtils.h>
  48.     #include <Memory.h>
  49. #endif
  50.  
  51. #include <SetupA4.h>            // these aren't in macheaders
  52. #include <Power.h>
  53. #include <Retrace.h>
  54.  
  55.  
  56. // the purpose of the following is to provide an easy way to save and restore the world.
  57. // it was added after not being able to hunt down the weird GetWTitle crash. it may be
  58. // overkill.
  59.  
  60. #define kSaveRegList    a0-a5/d0-d7
  61. #define    SaveTheWorld    asm    { movem.l    kSaveRegList,-(sp) }
  62. #define RestoreTheWorld asm { movem.l    (sp)+,kSaveRegList }
  63.  
  64.  
  65. // this isn't defined in any .h file that I could find
  66.  
  67. typedef struct DeferredTask    {
  68.     QElemPtr    qLink;
  69.     short        qType;
  70.     short        dtFlags;
  71.     ProcPtr        dtAddr;
  72.     long        dtParm;
  73.     long        dtReserved;
  74. }    DeferredTask;
  75.  
  76.  
  77. #define        kNotApplicableIcon    131            // icon displayed if the mac is an inappropriate one
  78. #define        kErrVblInstallIcon    130            // vinstall failure at init time
  79. #define        kErrRsrcInstallIcon    129            // detatchresource failure at init time
  80. #define        kOKInstallIcon        128            // installed fine
  81.  
  82. #define        kVBLInterval        10*60        // # seconds * ticks between vbl executions
  83.  
  84.  
  85. // prototypes
  86. pascal void        SHOWINIT(short iconID, short moveX);
  87. pascal void        PCPVBL(void);
  88. pascal void        PCPDTask(void);
  89.  
  90.  
  91. // globals - think c provides the ability to do globals in code resources by referencing them
  92. // off a4. all you have to do is stash the beginning of the code rsrc away at init time, set up
  93. // a4, and then restore it again when you're done.
  94. // think provides pre-zeroed space at the end of the code rsrc for the globals - no additional
  95. // allocation or anything else is necessary.
  96.  
  97. VBLTask            gVTaskBlk;
  98. DeferredTask    gDTaskBlk;
  99. Boolean            gDidIDisableIdle;    // must make sure DisableIdles and EnableIdles are balanced
  100.  
  101.  
  102. void
  103. main()
  104. {
  105.     Ptr            lOurAddress;
  106.     long        lGestaltResponse;
  107.     OSErr        lErr;
  108.  
  109.  
  110.     RememberA0();                            // glue from think's setupa4.h which stashes away
  111.                                             // a pointer to the beginning of the rsrc for
  112.                                             // later use.
  113.  
  114.     SetUpA4();                                // sets up a4 for globals.
  115.  
  116.     asm {
  117.         move.l    A0, lOurAddress                ; A0 points to the beginning of the
  118.                                             ; INIT, courtesy of the THINK glue
  119.     }
  120.  
  121.     lErr = Gestalt(gestaltPowerMgrAttr, &lGestaltResponse);
  122.     if (lErr != noErr ||
  123.     lGestaltResponse == gestaltUnknownErr ||
  124.     lGestaltResponse == gestaltUndefSelectorErr)    {
  125.         SHOWINIT(kNotApplicableIcon, -1);
  126.         RestoreA4();
  127.         return;
  128.     }
  129.     if (!(lGestaltResponse & 1))    {        // PMgrExists - is there a power mgr?
  130.         SHOWINIT(kNotApplicableIcon, -1);
  131.         RestoreA4();
  132.         return;
  133.     }
  134.     if (!(lGestaltResponse & 2))    {        // PMgrCPUIdle - is the cpu capable of idling?
  135.         SHOWINIT(kNotApplicableIcon, -1);
  136.         RestoreA4();
  137.         return;
  138.     }
  139.     
  140.     DetachResource(RecoverHandle(lOurAddress));        // make myself permanent only if it's sensible
  141.     if (ResError() != noErr)    {
  142.         SHOWINIT(kErrRsrcInstallIcon, -1);
  143.         RestoreA4();
  144.         return;
  145.     }
  146.  
  147.     gVTaskBlk.qType = vType;
  148.     gVTaskBlk.vblAddr = (VBLProcPtr) PCPVBL;
  149.     gVTaskBlk.vblCount = kVBLInterval;        // frequency of execution
  150.  
  151.     lErr = VInstall((QElemPtr) &gVTaskBlk);    // install my vbl task
  152.     if (lErr != noErr)    {
  153.         SHOWINIT(kErrVblInstallIcon, -1);
  154.         RestoreA4();
  155.         return;
  156.     }
  157.  
  158.     SHOWINIT(kOKInstallIcon, -1);            // installed ok - show "normal" icon
  159.  
  160.     RestoreA4();
  161. }
  162.  
  163.  
  164. pascal void
  165. PCPVBL()
  166. {
  167.     OSErr    lErr;
  168.  
  169.  
  170. #ifdef DEBUG
  171.     Debugger();
  172. #endif
  173.  
  174.     SaveTheWorld                            // a macro that expands - see above
  175.  
  176.     SetUpA4();
  177.  
  178.     gDTaskBlk.qLink = (QElemPtr) 0L;
  179.     gDTaskBlk.qType = dtQType;
  180.     gDTaskBlk.dtFlags = 0;
  181.     gDTaskBlk.dtAddr = (ProcPtr) PCPDTask;
  182.     gDTaskBlk.dtParm = 0L;
  183.     gDTaskBlk.dtReserved = 0L;
  184.  
  185.     lErr = DTInstall((QElemPtr) &gDTaskBlk);    // install a deferred task
  186.  
  187. #ifdef DEBUG
  188.     if (lErr != noErr)
  189.         DebugStr("\pDTInstall failed");
  190. #endif
  191.  
  192.     gVTaskBlk.vblCount = kVBLInterval;        // frequency of execution of the vbl. need to reset
  193.                                             // this every time otherwise i won't be executed
  194.                                             // ever again.
  195.  
  196.     RestoreA4();                            // restorea4 and restoretheworld must be in the
  197.                                             // correct order, otherwise bad things happen
  198.  
  199.     RestoreTheWorld
  200. }
  201.  
  202.  
  203. pascal void
  204. PCPDTask()
  205. {
  206.     Byte    lStatus, lPower;
  207.     OSErr    lErr;
  208.  
  209.  
  210. #ifdef DEBUG
  211.     Debugger();
  212. #endif
  213.  
  214.     SaveTheWorld
  215.  
  216.     SetUpA4();
  217.  
  218.     lErr = BatteryStatus(&lStatus, &lPower);
  219.  
  220. #ifdef DEBUG
  221.     if (lErr != noErr)
  222.         DebugStr("\pBatteryStatus failed");
  223. #endif
  224.  
  225.     if (lStatus & 1)    {                    // charger connected?
  226.         if (!gDidIDisableIdle)    {
  227.             DisableIdle();
  228.             gDidIDisableIdle = true;
  229.         }
  230.     }
  231.     else    {
  232.         if (gDidIDisableIdle)    {
  233.             EnableIdle();
  234.             gDidIDisableIdle = false;
  235.         }
  236.     }
  237.  
  238.     RestoreA4();
  239.  
  240.     RestoreTheWorld
  241. }
  242.